import socket
import threading
from concurrent.futures import ThreadPoolExecutor

import wx

from utils import time_util


class Server(wx.Frame):
    def __init__(self):
        # 服务器的启动状态
        self.isOn = False
        self.sk = socket.socket()
        self.sk.bind(('127.0.0.1', 6006))
        self.sk.listen(10)
        # 客户端
        self.client_dict = {}
        self.pool = ThreadPoolExecutor(max_workers=10)

        super().__init__(None, title='多人聊天室服务器', size=(500, 510))
        self.pl = wx.Panel(self)
        wx.Button(self.pl, label='启动服务器', pos=(10, 10), size=(220, 40)).Bind(wx.EVT_BUTTON,
                                                                                  self.click_start_server)
        wx.Button(self.pl, label='保存聊天记录', pos=(260, 10), size=(220, 40)).Bind(wx.EVT_BUTTON,
                                                                                     self.click_save_chat_record)
        self.chat_text = wx.TextCtrl(self.pl, pos=(10, 60), size=(470, 400), style=wx.TE_READONLY | wx.TE_MULTILINE)

    def click_start_server(self, event):
        if not self.isOn:
            self.isOn = True
            # 创建线程
            main_thread = threading.Thread(target=self.main_thread_fun)
            main_thread.damon = True
            main_thread.start()
            self.chat_text.AppendText(Server.format_data('【服务器通知】服务器启动成功！'))

    def click_save_chat_record(self, event):
        with open('chat_record.txt', 'a+', encoding='utf8') as f:
            f.write(self.chat_text.GetValue())
            data = Server.format_data('【服务器通知】服务器保存聊天记录成功！')
            f.write(data + '\n\n')
            self.chat_text.AppendText(data)

    def main_thread_fun(self):
        while self.isOn:
            conn, addr = self.sk.accept()
            client_name = conn.recv(1024).decode('utf8')
            client_thread = ClientThread(conn, client_name, self)
            # 保存客户端
            self.client_dict[client_name] = client_thread
            self.pool.submit(client_thread.run)
            self.send(f'【服务器通知】欢迎{client_name}进入聊天室！')

    @staticmethod
    def format_data(data):
        return time_util.get_time() + '：' + data.strip() + '\n'

    def send(self, data):
        data = Server.format_data(data)
        self.chat_text.AppendText(data)
        for client in self.client_dict.values():
            if client.isOn:
                client.conn.send(data.encode('utf8'))


class ClientThread(threading.Thread):
    def __init__(self, conn, name, server):
        threading.Thread.__init__(self)
        self.conn = conn
        self.client_name = name
        self.server = server
        self.isOn = True

    def run(self):
        while self.isOn:
            data = self.conn.recv(1024).decode('utf8')
            if data == '断开连接':
                self.isOn = False
                self.server.send(f'【服务器通知】{self.client_name}离开了聊天室！')
            else:
                self.server.send(f'【{self.client_name}】{data}')
        self.conn.close()


if __name__ == '__main__':
    app = wx.App()
    Server().Show()
    app.MainLoop()
